package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 定义的切面来执行公共字段填充拦截使用
 */
@Aspect//定义当前类是切面类
@Component//当前切面类交给ioc来管理
@Slf4j
public class AutoFillAspect {

    /**
     * 定义一个切点
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointCut(){};

    /**
     * 前置通知，来实现自动填充的业务
     * @param joinPoint
     */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint){
        log.info("开始执行前置通知");
        //1.获取签名对象
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //2.获取方法上的自定义注解对象
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);
        //3.获取注解的value属性值，通过枚举类判断当前执行的到底是修改还是新增
        OperationType operationType = autoFill.value();


        //4.目标方法的参数
        Object[] args = joinPoint.getArgs();
        //在执行自动填充功能中，必须要有参数，如果没有参数，则直接返回
        if(args==null || args.length<=0){
            return;
        }
        //5.取出第一个参数，其实就是对应的实体类
        Object entity = args[0];


        //获取当前时间以及当前登录人
        LocalDateTime time = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();

        try {
        //6.如果是新增，则为四个属性赋值
        if(operationType==OperationType.INSERT){
                //获取set四个方法
                Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                //利用反射机制进行赋值处理
                setCreateTime.invoke(entity,time);
                setCreateUser.invoke(entity,currentId);
                setUpdateTime.invoke(entity,time);
                setUpdateUser.invoke(entity,currentId);

        } else{
            //7.如果是修改，则为两个属性赋值
            Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
            setUpdateTime.invoke(entity,time);
            setUpdateUser.invoke(entity,currentId);
        }

        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}
